package com.xu.boot.config;

import ch.qos.logback.core.db.DBHelper;
import com.xu.boot.bean.Pet;
import com.xu.boot.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.*;

/**
 * 1. Configuration 注解告诉 SpringBoot 这是一个配置类 == bean.xml 配置文件
 * 2. 配置类里面使用 @Bean 标注在方法上给容器中注册组件，默认也是单实例的
 * 3. proxyBeanMethods：代理 bean 的方法，如果为 true 的话，外部无论对配置类中的这个组件
 *    注册方法调用多少次获取的都是之前注册容器中的单实例对象
 *      Full(proxyBeanMethods = true): 保证每个 @Bean 方法被调用多少次返回的组件都是单实例的
 *      Lite(proxyBeanMethods = false): 每个 @Bean 方法被调用多少次返回的组件都是新创建的
 *      ■ 配置类组件之间无依赖关系用 Lite 模式加速容器启动过程，减少判断
 *      ■ 配置类组件之间有依赖关系，方法会被调用得到之前单实例组件，用 Full 模式
 * 4. @Import({User.class, DBHelper.class})
 *     Springboot 中 @Import 可以把普通的类定义为 Bean，并且把这些 Bean 导入到容器中
 *     给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
 *     这样的话，容器中就存在两个 User 类实例，@Import 导入的和下面 @Bean 注解导入的
 *    4.1 @Import 引入普通类
 *        首先，@Import 引入普通的类可以帮助我们把普通的类定义为 Bean。@Import 可以添加在 @SpringBootApplication (启动类)、
 *        以及 @Configuration(配置类)、@Component(组件类) 对应的类上。@RestController、@Service、@Repository 都属于 @Component
 *    4.2 @Import 引入配置类 (@Configuration 修饰的类)
 *        另外，@Import 除了可以把普通的类定义为 Bean，@Import 还可以引入一个 @Configuration 修饰的类(引入配置类)，
 *        从而把让配置类生效(配置类下的所有 Bean 添加到 IOC 容器里面去)。在自定义 starter 的时候经常会用到。
 * 5. @ImportResource 注解用来导入原生的 beans.xml 配置文件
 */
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false)
@ImportResource("classpath:beans.xml")
public class MyConfig {

    /**
     * 给容器中添加组件，以方法作为组件的 id，返回的类型就是组件类型。返回的值，就是组件在容器中的实例
     * 也可以使用 @Bean("your-object-name") 来重新指定 bean 的名称
     * 注册的组件默认是单实例的
     *
     * 注解 @ConditionalOnBean 意思是满足 Conditional 指定的条件，则进行组件注入
     * 这里指的是只有当容器中存在名称为 tom 的 bean 时，就会装配 user01 这个 bean，否则不进行装配
     */
    @Bean
    @ConditionalOnBean(name = "tom")
    public User user01(){
        return new User("ZHANGSAN", 18);
    }

    @Bean("tom")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }

}
